package org.spring.aop.framework;

import org.spring.aop.AdvisedSupport;
import org.spring.aop.SpringProxy;
import org.tool.TipException;

import java.lang.reflect.Proxy;

/**
 * 默认 {@link AopProxyFactory} 实现，创建 CGLIB 代理或 JDK 动态代理。
 * <p>
 * 如果给定的 {@link AdvisedSupport} 实例满足以下条件之一，则创建 CGLIB 代理：
 * <ul>
 * <li>设置了 {@code optimize} 标志
 * <li>{@code proxyTargetClass} 标志已设置
 * <li>没有指定代理接口
 * </ul>
 * <p>
 * 通常，指定 {@code proxyTargetClass} 以强制执行 CGLIB 代理，或指定一个或多个接口以使用 JDK 动态代理。
 *
 * @author 李坤
 * @date 2022/4/18 19:30
 */
public class DefaultAopProxyFactory implements AopProxyFactory {

    @Override
    public AopProxy createAopProxy(AdvisedSupport advised) throws TipException {
        // 判断使用哪种代理方式
        if (advised.isUseCglibProxy() || this.hasNoUserSuppliedProxyInterfaces(advised)) {
            Class<?> targetClass = advised.getTargetClass();

            // 如果没有指定代理接口，则使用 CGLIB 代理
            if (!(targetClass.isInterface() || Proxy.isProxyClass(targetClass))) {
                return new CglibAopProxy(advised);
            }
        }
        return new JdkDynamicAopProxy(advised);
    }

    /*--------------------------------------------------private methods-----------------------------------------------*/

    /**
     * 确定提供的 {@link AdvisedSupport} 是否仅指定了 {@link SpringProxy} 接口（或根本没有指定代理接口）。
     */
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport advised) {
        Class<?>[] interfaces = advised.getProxiedInterfaces();
        return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.isAssignableFrom(interfaces[0])));
    }

}
